cmake_minimum_required (VERSION 2.6)
if( NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS )
  set( CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON )
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
project( uconn )
set ( UCONN_VERSION_MAJOR 0 )
set ( UCONN_VERSION_MINOR 1 )
find_package( LibCheck REQUIRED )
include_directories(${LibCheck_INCLUDE_DIRS})
set( LIBS ${LIBS} ${LibCheck_STATIC_LIBRARY_PATH} )
include( CheckTypeSize )

## Some useful type sizes
CHECK_TYPE_SIZE("char"               UCONN_CHAR_SIZE)
CHECK_TYPE_SIZE("short"              UCONN_SHORT_SIZE)
CHECK_TYPE_SIZE("int"                UCONN_INT_SIZE)
CHECK_TYPE_SIZE("long"               UCONN_LONG_SIZE)
CHECK_TYPE_SIZE("size_t"             UCONN_SIZE_T_SIZE)
CHECK_TYPE_SIZE("void*"              UCONN_POINTER_SIZE)
CHECK_TYPE_SIZE("unsigned short"     UCONN_USHORT_SIZE)
CHECK_TYPE_SIZE("unsigned int"       UCONN_UINT_SIZE)
CHECK_TYPE_SIZE("unsigned long"      UCONN_ULONG_SIZE)
CHECK_TYPE_SIZE("unsigned long long" UCONN_ULONGLONG_SIZE)
CHECK_TYPE_SIZE("float"              UCONN_FLOAT_SIZE)
CHECK_TYPE_SIZE("double"             UCONN_DOUBLE_SIZE)

## Find a suitable integer types of 64 bit length
CHECK_TYPE_SIZE("uint64_t" UCONN_UINT64_T_SIZE)
if( HAVE_UCONN_UINT64_T_SIZE)
  set(UCONN_INT64 int64_t)
  set(UCONN_UINT64 uint64_t)
else()
  ## Ok, we have to do this the hard way
  if( UCONN_UINT_SIZE MATCHES "8")
    set(UCONN_INT64        "int")
    set(UCONN_UINT64       "unsigned int")
  elseif( UCONN_ULONG_SIZE MATCHES "8")
    set(UCONN_INT64        "long")
    set(UCONN_UINT64       "unsigned long")
  elseif( UCONN_ULONGLONG_SIZE MATCHES "8")
    set(UCONN_INT64        "long long")
    set(UCONN_UINT64       "unsigned long long")
  else()
    MESSAGE(SEND_ERROR "Could not find appropriate numeric type for 64bit integers!")
  endif()
endif()

## Define a suitable pointer type
if( UCONN_POINTER_SIZE MATCHES ${UCONN_UINT_SIZE} )
  set( UCONN_POINTERSIZEUINT_TYPE "unsigned int" )
elseif( UCONN_POINTER_SIZE MATCHES ${UCONN_ULONG_SIZE} )
  set( UCONN_POINTERSIZEUINT_TYPE "unsigned long" )
elseif( UCONN_POINTER_SIZE MATCHES ${UCONN_SIZE_T_SIZE} )
  set( UCONN_POINTERSIZEUINT_TYPE "size_t" )
else()
  MESSAGE( SEND_ERROR "Could not find appropriate integer type of same size as void*" )
endif()

## Define a 32-bit type
CHECK_TYPE_SIZE("uint32_t" UCONN_UINT32_T_SIZE)
if( HAVE_UCONN_UINT32_T_SIZE)
  set( UCONN_INT32      "int32_t" )
  set( UCONN_UINT32     "uint32_t" )
elseif( UCONN_INT_SIZE MATCHES "4" )
  set( UCONN_INT32      "int" )
  set( UCONN_UINT32     "unsigned int" )
elseif( UCONN_LONG_SIZE MATCHES "4" )
  set( UCONN_INT32      "long" )
  set( UCONN_UINT32     "unsigned long" )
else()
  MESSAGE(SEND_ERROR "Could not find appropriate numeric type for 32bit int")
endif()

CHECK_TYPE_SIZE("uint16_t" UCONN_UINT16_T_SIZE)
if( HAVE_UCONN_UINT16_T_SIZE)
  set(UCONN_INT16  "int16_t")
  set(UCONN_UINT16 "uint16_t")
elseif( UCONN_SHORT_SIZE MATCHES "2")
  set(UCONN_INT16  "short")
  set(UCONN_UINT16 "unsigned short")
elseif( UCONN_INT_SIZE MATCHES "2")
  set(UCONN_INT16  "int")
  set(UCONN_UINT16 "unsigned int")
elseif( UCONN_CHAR_SIZE MATCHES "2")
  set(UCONN_INT16  "char")
  set(UCONN_UINT16 "unsigned char")
else()
  MESSAGE(SEND_ERROR "Could not find appropriate numeric type for 16bit int")
endif()
configure_file (
  "${PROJECT_SOURCE_DIR}/uconn_config.h.in"
  "${PROJECT_BINARY_DIR}/libuconn/uconn_config.h"
  )
if(MSVC)
  # Force to always compile with W4
  if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
  else()
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
  endif()
elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUC)
  # Update if necessary
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-long-long -pedantic")
endif()
include_directories( "${PROJECT_BINARY_DIR}" )
#include_directories( "${PROJECT_SOURCE_DIR}" )

if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
else( CMAKE_SIZEOF_VOID_P EQUAL 4 )
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
endif( CMAKE_SIZEOF_VOID_P EQUAL 4 )

add_library( uconn STATIC 
  uconn.h
  ucfront.h
  ucfront.c
  ucerror.h
  ucerror.c
  ucwarning.h
  ucwarning.c
  ucinfo.h
  ucinfo.c
  ucdebug.h
  ucdebug.c
  uclog.h
  uclog.c
  front-ends/ucfront_console.h
  front-ends/ucfront_console.c
)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/uconn.h ${PROJECT_BINARY_DIR}/libuconn/uconn.h COPYONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/ucfront.h ${PROJECT_BINARY_DIR}/libuconn/ucfront.h COPYONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/ucerror.h ${PROJECT_BINARY_DIR}/libuconn/ucerror.h COPYONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/ucwarning.h ${PROJECT_BINARY_DIR}/libuconn/ucwarning.h COPYONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/ucinfo.h ${PROJECT_BINARY_DIR}/libuconn/ucinfo.h COPYONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/ucdebug.h ${PROJECT_BINARY_DIR}/libuconn/ucdebug.h COPYONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/uclog.h ${PROJECT_BINARY_DIR}/libuconn/uclog.h COPYONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/front-ends/ucfront_console.h ${PROJECT_BINARY_DIR}/libuconn/ucfront_console.h COPYONLY)

add_executable( front_console
  example/front_console.c
)
target_link_libraries( front_console uconn )
install( TARGETS uconn 
         DESTINATION lib )
install( FILES "${PROJECT_BINARY_DIR}/libuconn/*.h"        
         DESTINATION include/libuconn )
# build a CPack driven installer package
include( InstallRequiredSystemLibraries )
set( CPACK_RESOURCE_FILE_LICENSE  
     "${CMAKE_CURRENT_SOURCE_DIR}/COPYING" )
set( CPACK_PACKAGE_VERSION_MAJOR "${UCONN_VERSION_MAJOR}" )
set( CPACK_PACKAGE_VERSION_MINOR "${UCONN_VERSION_MINOR}" )
include( CPack )
